
package todolist.util;

import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import todolist.personalization.ErrorMessages;

/**
 * For sending email. Singleton.
 * Libraries required: mail.jar
 * @author YouLi
 * @author Ivan
 */
public class Email {
	
	// handle singleton instance

	private static Email _objEmail;
	
	public static Email getInstance() {
		if (_objEmail == null)
			_objEmail = new Email();
		return _objEmail;
	}
	
	// member attributes
	
	private Session _objSession;
	private String _strError;

	/**
	 * Initialises properties only once.
	 */
	private Email() {
		ConfigFileIO objConfig = ConfigFileIO.getInstance();
		_strError = objConfig.getError();
		if (_strError != null)
			return; // if error during loading config
		Properties objEmailProps = new Properties();
		objEmailProps.put("mail.smtp.auth", "true");
		objEmailProps.put("mail.smtp.starttls.enable", "true");
		objEmailProps.put("mail.smtp.connectiontimeout", objConfig.getTimeout());
		objEmailProps.put("mail.smtp.timeout", objConfig.getTimeout());
		objEmailProps.put("mail.smtp.host", objConfig.getSendingHost());
		objEmailProps.put("mail.smtp.port", objConfig.getSendingPort());
		PasswordAuthenticator objAuth = new PasswordAuthenticator();
		_strError = objAuth.validatePasswordAuthentication();
		if (_strError == null)
			_objSession = Session.getInstance(objEmailProps, objAuth);
	}
	
	private class PasswordAuthenticator extends Authenticator {

		/**
		 * Returns error message if decryption failed.
		 */
		private String validatePasswordAuthentication() {
			String strCipherPassword = ConfigFileIO.getInstance().getSendingPassword();
			String strPlainText = Encryption.getInstance().decrypt(strCipherPassword);
			if (strPlainText == null)
				return ErrorMessages.ERR_DECRYPT_FAILED;
			return null;
		}

		@Override
		protected PasswordAuthentication getPasswordAuthentication() {
			String strSenderMail = ConfigFileIO.getInstance().getSendingEmailAdd();
			String strCipherPassword = ConfigFileIO.getInstance().getSendingPassword();
			String strPlainText = Encryption.getInstance().decrypt(strCipherPassword);
			assert strPlainText != null;
			return new PasswordAuthentication(strSenderMail, strPlainText);
		}
		
	}

	/**
	 * Sends email, returns error message if any, or else null.
	 * @throws IllegalArgumentException
	 */
	public String sendEmail(String pstrEmailSubject, String pstrEmailContent) throws IllegalArgumentException {
		if (_strError != null)
			return _strError; // if error during init
		if (pstrEmailSubject == null)
			throw new IllegalArgumentException("Email.sendEmail() : Email subject must not be null or empty.");
		if (pstrEmailContent == null)
			throw new IllegalArgumentException("Email.sendEmail() : Email content must not be null or empty.");
		ConfigFileIO objConfig = ConfigFileIO.getInstance();
		_strError = objConfig.getError();
		if (_strError != null)
			return _strError; // if error during loading config
		String strSenderMail = objConfig.getSendingEmailAdd();
		String strReceiverMail = objConfig.getReceivingEmailAdd();
		try {
			Message objMessage = new MimeMessage(_objSession);
			objMessage.setFrom(new InternetAddress(strSenderMail)); // from
			objMessage.setRecipients(Message.RecipientType.TO,
				InternetAddress.parse(strReceiverMail)); // to
			objMessage.setSubject(pstrEmailSubject);
			objMessage.setText(pstrEmailContent);
			Transport.send(objMessage);
		} catch (MessagingException e) {
			return ErrorMessages.ERR_EMAIL_FAILED_TO_SEND;
		}
		return null; // on success
	}
	
}
